Since 2015, JavaScript has improved immensely.
It’s much more pleasant to use it now than ever.
In this article, we’ll look at JavaScript iterable objects.
Iterable Computed Data
Iterable content can come from computed data.
Methods can return iterable objects that we can iterate through.
We have 3 methods that return iterable objects. They include the entries
, keys
, and values
method.
entries
returns an iterable over the entries encoded as key-value arrays.
For arrays, the keys are indexes and the values are the elements.
For sets, the keys and values are both the elements.
keys
returns an iterable object with the keys of the entries.
values
returns an iterable object with the values of the entries.
For instance, we can write:
const arr = ['foo', 'bar', 'baz'];
for (const [key, value] of arr.entries()) {
console.log(key, value);
}
Then we get:
0 "foo"
1 "bar"
2 "baz"
logged.
Maps and Sets
The Map
constructor turns an iterable key-value pairs into a map.
For instance, we can write:
const map = new Map([
['foo', 'one'],
['bar', 'two']
]);
Then we can call get
to get the value.
For example, we can write:
const foo = map.get('foo');
and returns 'one'
.
Likewise, we can pass in an array to the Set
constructor.
For instance, we can write:
const set = new Set(['red', 'green', 'blue']);
Then we can use the has
method to check whether the element exists.:
const hasRed = set.has('red');
WeakMaps and WeakSets work similarly.
Maps and sets are iterables themselves, but WeakMaps and WeakSets aren’t.
Promises
Promise.all
and Promise.race
takes iterables over promises.
So we can write:
Promise.all([
Promise.resolve(1),
Promise.resolve(2),
]).then(() => {
//...
});
to run an array of promises in parallel.
Promise.race
resolves to the value of the first promise from an array of promises.
For example, we can write:
Promise.race([
Promise.resolve(1),
Promise.resolve(2),
]).then(() => {
//...
});
to resolve to the value of the first promise that finishes.
Implementing Iterables
JavaScript iterable objects have the Symbol.iterator
method.
The method returns an object with the value
and done
properties.
value
has the value we return from the iterable.
And done
indicates whether there’re any values left. If it’s true
then there’s no value left to return.
For example, we can write:
const obj = {
[Symbol.iterator]() {
let step = 0;
const iterator = {
next() {
if (step <= 2) {
step++;
}
switch (step) {
case 1:
return {
value: 'foo', done: false
};
case 2:
return {
value: 'bar', done: false
};
default:
return {
value: undefined, done: true
};
}
}
};
return iterator;
}
};
The Symbol.iterator
method returns an object according to the step
number.
Then we can use the for-of loop to confirm that the object is iterable:
for (const x of obj) {
console.log(x);
}
We should get:
foo
bar
logged.
We can omit done
if it’s false
and omit the value
if it’s undefined
.
So we can write:
switch (step) {
case 1:
return {
value: 'foo'
};
case 2:
return {
value: 'bar'
};
default:
return {
done: true
};
}
Conclusion
Iterable objects have special methods that distinguish them.